package cn.bugstack.trigger.job;

import cn.bugstack.domain.task.model.entity.TaskEntity;
import cn.bugstack.domain.task.service.ITaskService;
import cn.bugstack.middleware.db.router.strategy.IDBRouterStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 扫描数据库中的记录找到那些是未发送的消息
 */

@Slf4j
@Component()
public class SendMessageTaskJob {
    @Resource
    private ITaskService taskService;
    @Resource
    private ThreadPoolExecutor executor;
    @Resource
    private IDBRouterStrategy dbRouter;


    @Scheduled(cron = "0/5 * * * * ?")
    public void exec() {
        try {
//            获取分库数量
            int dbCount = dbRouter.dbCount();

            for (int dbIdx = 1; dbIdx <= dbCount; dbIdx++) {
                int finalDbIdx = dbIdx;
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            dbRouter.setDBKey(finalDbIdx);
                            dbRouter.setTBKey(0);
                            List<TaskEntity> taskEntities = taskService.queryNoSendMessageTaskList();
                            log.info("测试结果：{}", taskEntities.size());
                            if (taskEntities.isEmpty()) return;

//                            发送MQ消息
                            for (TaskEntity taskEntity : taskEntities) {
//                                开启线程发送，提高发送效率，配置的线程池策略为CallerRunsPolicy，在 ThreadPoolConfig 配置中有4个策略，面试中容易对比提问。可以检索下相关资料。
                                executor.execute(() -> {
                                    try {
                                        taskService.sendMessage(taskEntity);
                                        taskService.updateSendMessageCompleted(taskEntity.getMessageId(), taskEntity.getMessageId());
                                    } catch (Exception e) {
                                        log.error("定时任务，发送MQ消息失败 userId: {} topic: {}", taskEntity.getUserId(), taskEntity.getTopic());
//                                        log.error("idx:{}",finalDbIdx);
                                        taskService.updateSendMessageFail(taskEntity.getUserId(), taskEntity.getMessageId());
                                    }
                                });
                            }
                        } finally {
                            dbRouter.clear();
                        }

                    }
                });
            }


//            List<TaskEntity> taskEntities = taskService.queryNoSendMessageTaskList();
//            log.info("测试结果：{}", taskEntities.size());
        } catch (Exception e) {
            log.error("定时任务，扫描MQ任务表发送消息失败。", e);
        } finally {
            dbRouter.clear();//todo 如果不清空会发生什么
        }

    }
}
